<?php

namespace App\Http\Controllers\OpenShop\Feishu;

use App\Enums\OpenShop\FeishuMini\ProgrammingEnum;
use App\Http\Controllers\BaseController;
use App\Http\Middleware\OpenShop\WangGuiCityByPower;
use App\Http\Validate\OpenShop\InvestmentPromotion\PlaceholderValidate;
use App\Http\Validate\OpenShop\SiteLocation\ShopValidate;
use App\Models\OpenShop\Common\OpenShopOrderManagerModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopMainProcessModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopSignOrderModel;
use App\Models\OpenShop\SiteLocation\OpenShopSiteLocationExamineLogModel;
use App\Models\OpenShop\SiteLocation\OpenShopSiteLocationModel;
use App\Service\Api\WangguiApiService;
use App\Service\OpenShop\Feishu\MapService;
use App\Service\OpenShop\Feishu\SelectionService;
use App\Service\OpenShop\Feishu\ShopManualService;
use App\Service\OpenShop\FeishuMini\SandTableService;
use App\Service\OpenShop\FeishuMini\ShopService;
use App\Service\OpenShop\OrderService;
use App\Service\OpenShop\SiteLocation\BusinessCircleService;
use App\Service\OpenShop\SiteLocation\MallService;
use App\Service\OpenShop\SiteLocation\PlaceHolderSiteLocationService;
use App\Service\Wanggui\WangguiDotService;
use Carbon\Carbon;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Js;
use Illuminate\Validation\ValidationException;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;

class SelectionController extends BaseController
{
    public function index(Request $request)
    {
        $username = (string)$request->get("username", "");
        return $this->success(SelectionService::getManagerList($username));
    }

    /**
     * @throws GuzzleException
     */
    public function getSiteTaskHandlerList(Request $request): JsonResponse
    {
        $username = (string)$request->get("username", "");
        return $this->success(SelectionService::getSiteTaskHandlerList($username));
    }

    /**
     * 重新选址
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function reSelection(Request $request): JsonResponse
    {
        $orderNo          = $request->get('orderNo', '');
        $changeType       = (int)$request->post('changeType');
        $changeReason     = (string)$request->post('changeReason', '');
        $province         = (int)$request->get('provinceCode', '');
        $city             = (int)$request->get('cityCode', '');
        $district         = (int)$request->get('districtCode', '');
        $addressPrefix    = (string)$request->get('addressPrefix', '');
        $selectLocation   = [
            'province' => $province,
            'city'     => $city,
            'district' => $district
        ];
        $developManagerId = (int)$request->get('developManagerId', '');

        $model  = new SelectionService($orderNo);
        $result = $model->reSelection($changeType, $changeReason, $selectLocation, $addressPrefix, $developManagerId);

        // TODO 添加日志
        return $this->success();
    }

    /**
     * 添加开发经理
     * @param Request $request
     * @return JsonResponse
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws ValidationException
     */
    public function addManager(Request $request)
    {
        $this->validate($request, [
            'managerId' => 'required|numeric',
            'orderNo'   => 'required|string',
        ]);
        $orderNo   = $request->post('orderNo', '');
        $managerId = $request->post('managerId', '');

        $placeholderInfo = PlaceholderValidate::insertValidate($request->get('placeholderInfo'));
        $rmsInfo         = getRmsUserInfoByAuth();
        SelectionService::addManager($orderNo, $managerId, $rmsInfo);

        (new PlaceHolderSiteLocationService($orderNo))->manageSavePlaceholder($placeholderInfo);
        return $this->success();
    }


    /**
     * 各种类型经理详情
     * @param Request $request
     * @param string $orderNo
     * @return JsonResponse
     */
    public function managerDetail(Request $request, string $orderNo)
    {
        $managerType = $request->get('managerType');
        if (!$managerType) {
            $managerType = OpenShopOrderManagerModel::MANAGER_TYPE_2;
        }

        return $this->success(SelectionService::managerDetail($orderNo, $managerType));
    }


    /**
     * 添加选址表单
     * @param Request $request
     * @return JsonResponse
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws ValidationException
     */
    public function addReport(Request $request)
    {
        $this->validate($request, [
            'shopArea'          => 'required',
            'shopRent'          => 'required|numeric',
            'shopDetailAddress' => 'required|string',
            'addressPrefix'     => 'required|string',
            'addressSelect'     => 'required|array',
            'shopType'          => 'required|string',
            'shopScopeProducts' => 'required|string',
            'orderNo'           => 'required|string',
            'cashType'          => 'required|integer',
            'openTime'          => 'required|string',
            'electricQuantity'  => 'required|integer',
            'isAddElectricNum'  => 'required|integer',
            'smokeNumber'       => 'required|integer',
            'isReformSmoke'     => 'required|integer',
            'isReformWater'     => 'required|integer',
            'cashTypeMapping'   => 'array'
        ]);
        $reqData             = $request->except('cashTypeMapping');
        $reqData['openTime'] = strtotime($reqData['openTime']);
        $mapping             = $request->cashTypeMapping;
        $rmsInfo             = getRmsUserInfoByAuth();
        SelectionService::addReport($reqData, $rmsInfo, $mapping);
        return $this->success();
    }

    /**
     * @throws ValidationException
     */
    public function getReportInfo(Request $request)
    {
        $this->validate($request, [
            'orderNo' => 'required|string',
        ]);
        $orderNo = $request->get('orderNo', '');
        return $this->success(SelectionService::getReportInfo($orderNo));
    }

    /**
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @throws ValidationException
     */
    public function saveDisclosure(Request $request)
    {
        $this->validate($request, [
            'id'      => 'required|numeric',
            'files'   => 'required|array',
            'orderNo' => 'required|string',
        ]);
        $files   = $request->post('files');
        $orderNo = $request->orderNo;
        $id      = $request->id;
        $rmsInfo = getRmsUserInfoByAuth();
        SelectionService::addDisclosure($id, $files, $orderNo, $rmsInfo);
        return $this->success();
    }

    public function setReportWithPower(Request $request, $orderNo)
    {
        return $this->setReport($request, $orderNo);
    }

    public function setReportWithOutPower(Request $request, $orderNo)
    {
        return $this->setReport($request, $orderNo);
    }

    public function setReport(Request $request, $orderNo)
    {
        $this->validate($request, [
            'shopArea'          => 'required',
            'shopRent'          => 'required|numeric',
            'shopDetailAddress' => 'required|string',
            'addressPrefix'     => 'required|string',
            'addressSelect'     => 'required|array',
            'shopType'          => 'required|string',
            'shopScopeProducts' => 'required|string',
            'cashType'          => 'required|integer',
            'openTime'          => 'required|string',
            'electricQuantity'  => 'required|integer',
            'isAddElectricNum'  => 'required|integer',
            'smokeNumber'       => 'required|integer',
            'isReformSmoke'     => 'required|integer',
            'isReformWater'     => 'required|integer',
            'cashTypeMapping'   => 'array'
        ]);
        $reqData             = $request->except('cashTypeMapping');
        $reqData['openTime'] = strtotime($reqData['openTime']);
        $mapping             = $request->cashTypeMapping;
        $rmsInfo             = getRmsUserInfoByAuth();
        SelectionService::setReport($orderNo, $reqData, $rmsInfo, $mapping);
        return $this->success();
    }


    /**
     * 获取选址网规地图数据
     * @param Request $request
     * @return JsonResponse
     */
    public function mapLists(Request $request): JsonResponse
    {
        return $this->success(MapService::getMapData());
    }

    /**
     * 获得地区中心点
     * @return JsonResponse
     */
    public function mapCenterPoint(): JsonResponse
    {
        return $this->success(MapService::mapCenterPoint());
    }

    /**
     * 获取选址网规地图数据
     * @param Request $request
     * @return JsonResponse
     */
    public function mapRank(Request $request): JsonResponse
    {
        return $this->success(MapService::mapRank());
    }

    /**
     * 全国省市区范围经纬度
     * @param Request $request
     * @return JsonResponse
     */
    public function mapRange(Request $request): JsonResponse
    {
        $pAdcode = (string)$request->get('pAdcode', '');
        $level   = (string)$request->get('level', '');
        return $this->success(MapService::mapRange($pAdcode, $level));
    }

    /**
     * 区域内店铺-列表
     * @param Request $request
     * @return JsonResponse
     */
    public function mapShopList(Request $request): JsonResponse
    {
        $params = ShopValidate::cityShopValidate($request->merge(["shopName" => $request->get('shopName', '')])->all());
        return $this->success(ShopService::cityShop($params));
    }

    /**
     * 单个店铺点位详细
     * @param Request $request
     * @param int $shopCode
     * @return JsonResponse
     * @throws GuzzleException
     */
    public function mapDetail(Request $request, int $shopCode): JsonResponse
    {
        return $this->success(MapService::mapDetail($shopCode));
    }

    /**
     * 城市内数据集列表
     * @param Request $request
     * @return JsonResponse
     */
    public function mapDataList(Request $request): JsonResponse
    {
        $city     = (string)$request->get('city', '');
        $district = (string)$request->get('district', '');
        $province = (string)$request->get('province', '');
        $data     = [];
        if ($city) {
            $data = MapService::mapDataList($city, '', '');
        }
        if ($district) {
            $data = MapService::mapDataList('', $district, '');
        }
        if ($province) {
            $data = MapService::mapDataList('', '', $province);
        }
        if ($request->header('platformname') == 'site') {
            unset($data['otherBrandShopData']);
        }
        return $this->success($data);
    }

    /**
     * 通过城市查询推荐区域
     * @param Request $request
     * @return JsonResponse
     */
    public function mapRecommend(Request $request): JsonResponse
    {
        $city = (string)$request->get('city', '');
        return $this->success(MapService::mapRecommend($city));
    }


    /**
     * 楼层导览
     * @param Request $request
     * @return JsonResponse
     * @throws ValidationException
     */
    public function floorGuide(Request $request): JsonResponse
    {
        $this->validate($request, [
            'mallId' => 'required|string'
        ]);
        $mallId = $request->get('mallId');
        return $this->success(MallService::floorGuide($mallId));
    }

    /**
     * @param Request $request
     * @return JsonResponse
     * @throws ValidationException
     * @throws \Exception
     */
    public function takeawayEstimate(Request $request): JsonResponse
    {
        $this->validate($request, [
            'lng'      => 'required',
            'lat'      => 'required',
            'wgNumber' => 'string',  //点位ID
        ]);

        $lng      = $request->get('lng');
        $lat      = $request->get('lat');
        $wgNumber = $request->get('wgNumber');

        return $this->success(WangguiDotService::takeawayEstimate($lng, $lat, $wgNumber));
    }


    /**
     * 获得图片
     * @param Request $request
     * @return JsonResponse
     * @throws ValidationException
     */
    public function drawnBaseMapImg(Request $request): JsonResponse
    {
        $this->validate($request, [
            'lng' => 'required',
            'lat' => 'required'
        ]);
        $lng = $request->get('lng');
        $lat = $request->get('lat');
        $key = WangGuiCityByPower::getRandomAmapKey();
        $url = "https://restapi.amap.com/v3/staticmap?location=%s,%s&zoom=17&size=1024*1024&key=$key";
        return $this->success(['url' => sprintf($url, $lng, $lat)]);
    }


    /**
     * @param Request $request
     * @return JsonResponse
     */
    public function brandTree(Request $request): JsonResponse
    {
        return $this->success(WangguiDotService::brandTree());
    }


    /**
     * @param Request $request
     * @return JsonResponse
     * @throws ValidationException
     */
    public function getStoreByMallIdAndFloor(Request $request): JsonResponse
    {
        $this->validate($request, [
            'mallId' => 'required',
            'floor'  => 'required',
        ]);
        $mallId = $request->get('mallId');
        $floor  = $request->get('floor');
        return $this->success(MallService::getStoreByMallIdAndFloor($mallId, $floor));
    }


    /**
     * @param Request $request
     * @return JsonResponse
     * @throws ValidationException
     */
    public function getRecommendFloorStoreByMallId(Request $request): JsonResponse
    {
        $this->validate($request, [
            'mallId' => 'required',
        ]);
        $mallId = $request->get('mallId');
        return $this->success(MallService::getRecommendFloorStoreByMallId($mallId));
    }


    /**
     * 动线标注手绘图上传
     * @param Request $request
     * @param $id
     * @return JsonResponse
     * @throws ValidationException
     */
    public function uploadHandDrawImg(Request $request, $id): JsonResponse
    {
        $this->validate($request, [
            'file' => 'required|array'
        ]);
        $fileArr = $request->get('file');
        WangguiDotService::uploadHandDrawImg($fileArr, $id);
        return $this->success();
    }


    /**
     * 根据城市Code获得商圈边界
     * @param Request $request
     * @return JsonResponse
     */
    public function getBusinessBoundaryByCityCode(Request $request): JsonResponse
    {
        $cityCode     = $request->get('cityCode', 0);
        $occupyStatus = (string)$request->get('occupyStatus', '');
        $capacity     = (string)$request->get('capacity', 0);
        return $this->success(WangguiDotService::getBusinessBoundaryByCityCode($cityCode, $occupyStatus, $capacity));
    }


    /**
     * 根据城市Code获得商圈边界
     * @param Request $request
     * @return JsonResponse
     */
    public function getBusinessBoundaryByCityCodeByPc(Request $request): JsonResponse
    {
        $cityCode     = $request->get('cityCode', 0);
        $occupyStatus = (string)$request->get('occupyStatus', '');
        $capacity     = (string)$request->get('capacity', 0);

        if ($occupyStatus == '') {
            return $this->success();
        }
        return $this->success(WangguiDotService::getBusinessBoundaryByCityCode($cityCode, $occupyStatus, $capacity));
    }

    /**
     * 商业圈详情
     */
    public function businessCircleDetail(Request $request, $id): JsonResponse
    {
        $rmsInfo = getRmsUserInfoByAuth();

        $data = BusinessCircleService::detail($id, $rmsInfo->id);
        return $this->success($data);
    }

    /**
     * 加盟商用户列表
     * @param Request $request
     * @return JsonResponse
     */
    public function franchiseeList(Request $request): JsonResponse
    {
        $id       = (int)$request->get('id', 0);
        $name     = (string)$request->get('name', '');
        $cityCode = (int)$request->post('cityCode');
        $pageNum  = (int)$request->get('pageNum', 1);
        $pageSize = (int)$request->get('pageSize', 10);

        $data = BusinessCircleService::franchiseeList($id, $name, $cityCode, $pageNum, $pageSize);

        return $this->success($data);
    }

    /**
     * 商圈添加记录
     * @param Request $request
     * @param $id
     * @return JsonResponse
     * @throws ValidationException
     */
    public function addRecordToBusinessCircle(Request $request, $id): JsonResponse
    {
        $this->validate($request, [
            'files'  => 'array',
            'record' => 'required|string'
        ]);

        $files  = (array)$request->post('files');
        $record = (string)$request->post('record');

        $rmsInfo = getRmsUserInfoByAuth();

        BusinessCircleService::addRecordToBusinessCircle($id, $files, $record, $rmsInfo->id, $rmsInfo->username);

        return $this->success();
    }

    /**
     * 添加预占址加盟商
     * @param Request $request
     * @param $id
     * @return JsonResponse
     */
    public function addPreOccupyToBusinessCircle(Request $request, $id): JsonResponse
    {
        $username = (string)$request->post('username', '');
        $mobile   = (string)$request->post('mobile', '');
        $rmsInfo  = getRmsUserInfoByAuth();

        BusinessCircleService::addPreOccupyToBusinessCircle($id, $username, $mobile, $rmsInfo->id, $rmsInfo->username);

        return $this->success();

    }


    public function deleteRecordToBusinessCircle(Request $request, $id): JsonResponse
    {
        BusinessCircleService::deleteRecordToBusinessCircle($id);
        return $this->success();
    }


    /**
     * 获得网页版点位大卡片
     * @param Request $request
     * @return JsonResponse
     * @throws ValidationException
     * @throws GuzzleException
     */
    public function floatCard(Request $request): JsonResponse
    {
        $this->validate($request, [
            'type' => 'required',
            'id'   => 'required'
        ]);
        $type    = $request->get('type');    //点位类型
        $id      = $request->get('id');      //主键ID
        $rmsInfo = getRmsUserInfoByAuth();
        return $this->success(SandTableService::floatCard($type, $id, $rmsInfo->id));
    }


    /**
     * 获得网规点位信息
     * @param Request $request
     * @return JsonResponse
     * @throws ValidationException
     */
    public function pointByPc(Request $request): JsonResponse
    {
        $this->validate($request, [
            'city' => 'string|required',
            //'northEast' => 'string|required',
            //'center'    => 'string|required',
            //'southWest' => 'string|required'
        ]);
        $city      = $request->get('city', '');
        $northEast = $request->get('northEast', '');
        $center    = $request->get('center', '');
        $southWest = $request->get('southWest', '');
        return $this->success(WangguiDotService::getPoint($city, $northEast, $center, $southWest));
    }


    /**
     * 竞品互补品分类
     * @param Request $request
     * @return JsonResponse
     */
    public function productType(Request $request): JsonResponse
    {
        $data = [
            'competition' => collect(ProgrammingEnum::BRAND_SAND_TABLE_COMPETITIVE_PRODUCTS_MAPPING)->map(function ($competition) {
                return [
                    'key'  => ProgrammingEnum::BRAND_SHOP_MAPPING[$competition] ?? 'product',
                    'text' => $competition
                ];
            })->toArray(),
            'complement'  => collect(ProgrammingEnum::BRAND_SAND_TABLE_COMPLEMENTARY_PRODUCTS_MAPPING)->map(function ($complement) {
                return [
                    'key'  => ProgrammingEnum::BRAND_SHOP_MAPPING[$complement] ?? 'product',
                    'text' => $complement
                ];
            })->toArray()
        ];

        return $this->success($data);
    }


    /**
     * 获取网规渗透率
     * @param Request $request
     * @return JsonResponse
     * @throws ValidationException
     */
    public function penetrationByCity(Request $request): JsonResponse
    {
        $this->validate($request, [
            'city' => 'required|string'
        ]);

        $city = $request->get('city');

        return $this->success(WangguiDotService::penetrationByCity($city));
    }

    /**
     * PC列表头
     * @return JsonResponse
     */
    public function listHeadByPc(): JsonResponse
    {
        return $this->success(
            collect(ProgrammingEnum::PC_TYPE_LIST_HEAD_MAPPING)->map(function ($type, $key) {
                return [
                    'text' => $type,
                    'type' => $key
                ];
            })->values()->toArray(),
        );
    }


    /**
     * 列表
     * @param Request $request
     * @return JsonResponse
     * @throws ValidationException
     */
    public function listByPc(Request $request): JsonResponse
    {
        $this->validate($request, [
            'city' => 'required|string',
            'type' => 'required|string',
        ]);

        $city         = $request->get('city', '');
        $type         = $request->get('type', '');
        $status       = $request->get('status', '');
        $area         = $request->get('area', '');
        $name         = $request->get('name', '');
        $gradeShop    = $request->get('gradeShop', '');
        $setInType    = $request->get('setInType', '');
        $shopType     = $request->get('shopType', '');
        $gradeWanggui = $request->get('gradeWanggui', '');
        $competition  = $request->get('competition', '');
        $complement   = $request->get('complement', '');
        $actualIncome = $request->get('shopActualIncome', '');
        $shopOpenStartDate = $request->get('shopOpenStartDate', '');
        $shopOpenEndDate   = $request->get('shopOpenEndDate', '');

        $pageNum  = $request->get('pageNum', 1);
        $pageSize = $request->get('pageSize', 20);

        return $this->success(WangguiDotService::listByPc($city, $type, $pageNum, $pageSize, $status, $gradeShop, $shopType, $area, $gradeWanggui, $name, $setInType, $competition, $complement, $actualIncome, $shopOpenStartDate, $shopOpenEndDate));
    }


    /**
     * 获得周边点位信息
     * @param Request $request
     * @return JsonResponse
     * @throws ValidationException
     */
    public function nearbyByPc(Request $request): JsonResponse
    {
        $this->validate($request, [
            'lng'      => 'required',
            'lat'      => 'required',
            'city'     => 'required',
            'distance' => 'required|int',
        ]);

        $lng      = $request->get('lng', 0);
        $lat      = $request->get('lat', 0);
        $distance = $request->get('distance', 0);
        $city     = $request->get('city', 0);

        return $this->success(WangguiDotService::nearbyByPc($lng, $lat, $distance, $city));
    }

    /**
     * PC版热力图
     * @param Request $request
     * @return JsonResponse
     * @throws ValidationException
     */
    public function heatMapByPc(Request $request): JsonResponse
    {
        $this->validate($request, [
            'city'       => 'required|string',
            'sourceType' => 'required|int|between:3,4',
        ]);

        $city       = $request->get('city');
        $sourceType = $request->get('sourceType');

        return $this->success(WangguiDotService::heatMap($city, $sourceType));
    }

    /**
     * 根据市获得每个区的聚合数据
     * @param Request $request
     * @return JsonResponse
     * @throws ValidationException
     */
    public function pointGatherByDistrict(Request $request): JsonResponse
    {
        $this->validate($request, [
            'city' => 'required|string',
        ]);

        $city         = $request->get('city', '');
        $shopStatus   = $request->get('shopStatus', '');
        $shopOpenStartDate = $request->get('shopOpenStartDate', '');
        $shopOpenEndDate = $request->get('shopOpenEndDate', '');
        $shopType     = $request->get('shopType', '');
        $shopName     = $request->get('shopName', '');
        $shopLevel    = $request->get('shopLevel', '');
        $shopArea     = $request->get('shopArea', '');
        $netLevel     = $request->get('netLevel', '');
        $netType      = $request->get('netType', '');
        $competition  = $request->get('competition', '');
        $complement   = $request->get('complement', '');
        $setInType    = $request->get('setInType', '');
        $actualIncome = $request->get('shopActualIncome', '');

        return $this->success(WangguiDotService::pointGatherByDistrict($city, $shopStatus, $shopType, $shopName, $shopLevel, $shopArea, $netLevel, $netType, $competition, $complement, $setInType, $actualIncome, $shopOpenStartDate, $shopOpenEndDate));
    }


    /**
     * 全国点位数据统计
     * @return JsonResponse
     */
    public function pointStatistics(): JsonResponse
    {
        return $this->success(WangguiDotService::pointStatistics());
    }

    /**
     * 根据shopCode获得营业趋势
     * @param Request $request
     * @return JsonResponse
     * @throws ValidationException
     */
    public function businessTrend(Request $request): JsonResponse
    {
        $this->validate($request, [
            'shopCode' => 'required'
        ]);

        $shopCode = $request->get('shopCode');

        return $this->success(WangguiDotService::businessTrend($shopCode));
    }


    /**
     * 点位预测
     * @param Request $request
     * @return JsonResponse
     * @throws ValidationException
     */
    public function getPredictionByWgNumber(Request $request): JsonResponse
    {
        $this->validate($request, [
            'wgNumber' => 'required|string'
        ]);

        $wgNumber = (string)$request->get('wgNumber');

        return $this->success(WangguiApiService::getPredictionByWgNumber($wgNumber));
    }


    /**
     * 历史点位预测
     * @param Request $request
     * @return JsonResponse
     * @throws ValidationException
     */
    public function getHistoricalPredictionByWgNumber(Request $request): JsonResponse
    {
        $this->validate($request, [
            'wgNumber' => 'required|string'
        ]);

        $wgNumber = (string)$request->get('wgNumber');

        return $this->success(WangguiApiService::getHistoricalPredictionByWgNumber($wgNumber));
    }


    /**
     * 戳点预测
     * @param Request $request
     * @return JsonResponse
     * @throws ValidationException
     */
    public function getPredictionByCoordinate(Request $request): JsonResponse
    {
        $this->validate($request, [
            'lng' => 'required',
            'lat' => 'required',
        ]);

        $lng = (float)$request->get('lng', 0);
        $lat = (float)$request->get('lat', 0);

        return $this->success(WangguiApiService::getPredictionByCoordinate($lng, $lat));
    }
}
